﻿using Abp.BackgroundJobs;
using Abp.Domain.Repositories;
using Abp.Domain.Services;
using Abp.Domain.Uow;
using Mt.Site.Core.BackGroundJobs;
using Mt.Site.Core.BackGroundJobs.Navigations;
using Mt.Site.Core.Navigations.Entities;
using Mt.Site.Core.Synchronization.Data;
using System;
using System.Threading.Tasks;

namespace Mt.Site.Core.Synchronization.Navigations
{
    public class MenuManualSyncManager : DomainService, IMenuManualSyncManager
    {
        private readonly IRepository<Menu, Guid> _menuRepository;
        private readonly IMenuStore _menuStore;

        public readonly ISynchronizationHelper _synchronizationHelper;

        private readonly IBackgroundJobManager _backgroundJobManager;

        public MenuManualSyncManager(
                IRepository<Menu, Guid> menuRepository,
                IMenuStore menuStore,
                ISynchronizationHelper synchronizationHelper,
                IBackgroundJobManager backgroundJobManager)
        {
            _menuRepository = menuRepository;
            _menuStore = menuStore;
            _synchronizationHelper = synchronizationHelper;
            _backgroundJobManager = backgroundJobManager;
        }

        public async Task<Guid> CreateOrUpdateMenuManualSync(CreateOrUpdateSynchorizeStore input, string fromLanguageName)
        {
            if (!_synchronizationHelper.ShouldSynchronize(input.ToTenantId))
            {
                return Guid.Empty;
            }

            return await UnitOfWorkManager.WithUnitOfWorkAsync(async () => 
            {
                using (CurrentUnitOfWork.DisableFilter(
                    AbpDataFilters.MayHaveTenant,
                    AbpDataFilters.MustHaveTenant,
                    MtSiteConsts.AbpDataFilters.MustHaveLanguage,
                    AbpDataFilters.SoftDelete))
                {
                    var fromEntry = await _menuRepository.FirstOrDefaultAsync(input.Id);
                    if (fromEntry != null)
                    {
                        Guid toMenuId;
                        if (fromEntry.TenantId == input.ToTenantId)
                        {
                            toMenuId = fromEntry.Id;
                        }
                        else
                        {
                            var toEntry = await _menuRepository.FirstOrDefaultAsync(
                                    item => item.AuxiliaryId == fromEntry.AuxiliaryId && item.TenantId == input.ToTenantId);

                            if (toEntry != null)
                            {
                                input.OptionType = OptionType.Update;
                                toMenuId = await _menuStore.UpdateMenuSync(toEntry, fromEntry);
                            }
                            else
                            {
                                input.OptionType = OptionType.Create;
                                toMenuId = await _menuStore.CreateMenuSync(fromEntry, input.ToTenantId);
                            }

                            if (toMenuId != Guid.Empty)
                            {
                                //同步样式和脚本
                               await _menuStore.StylesAndScriptsSync(fromEntry.Id, toMenuId, input.ToTenantId);
                            }
                        }
                        if (toMenuId != Guid.Empty)
                        {
                            // 同步路由
                            _synchronizationHelper.SyncRouteStr(fromEntry.Id, fromLanguageName, toMenuId, input.ToTenantId, input.TargetLanguage);

                            //自动同步子站的子站
                            await _backgroundJobManager.EnqueueAsync<SynchorizationMenuJob, BaseAndMenuIdArgs>(
                                    new BaseAndMenuIdArgs
                                    {
                                        Id = toMenuId,
                                        FromLanguage = input.TargetLanguage,
                                        FromTenantId = input.ToTenantId,
                                        MenuId = fromEntry.AuxiliaryId,
                                        OperateType = input.OptionType
                                    });
                            await _backgroundJobManager.EnqueueAsync<SynchorizationStylesJob, BaseAndMenuIdArgs>(
                                    new BaseAndMenuIdArgs
                                    {
                                        Id = toMenuId,
                                        FromLanguage = input.TargetLanguage,
                                        FromTenantId = input.ToTenantId,
                                        MenuId = fromEntry.AuxiliaryId,
                                        OperateType = input.OptionType
                                    });
                        }
                        return toMenuId;
                    }
                    return Guid.Empty;

                }
            });
        }

        public async Task<bool> StylesAndScriptsSyncManualSync(ManualSyncMenuStylesArgs input)
        {
            if (!_synchronizationHelper.ShouldSynchronize(input.ToTenantId))
            {
                return false;
            }

            return await UnitOfWorkManager.WithUnitOfWorkAsync(async () => {
                using (CurrentUnitOfWork.DisableFilter(
                    AbpDataFilters.MayHaveTenant,
                    AbpDataFilters.MustHaveTenant,
                    MtSiteConsts.AbpDataFilters.MustHaveLanguage,
                    AbpDataFilters.SoftDelete))
                {
                    //同步样式和脚本
                    await _menuStore.StylesAndScriptsSync(input.FromMenuId, input.ToMenuId, input.ToTenantId);

                    await _backgroundJobManager.EnqueueAsync<SynchorizationStylesJob, BaseAndMenuIdArgs>(
                            new BaseAndMenuIdArgs
                            {
                                Id = input.ToMenuId,
                                FromLanguage = input.TargetLanguage,
                                FromTenantId = input.ToTenantId,
                                OperateType = input.OptionType
                            });

                    return true;
                }
            });
        }
    }
}
